package http

import (
	"bufio"
	"bytes"
	"context"
	"fmt"
	"io"
	"log"
	"net"
	"sync/atomic"
	"time"

	"internal-net-bridge-server/internal/tunnel/core"
)

// ========================================
// HTTP协议监听器实现
// 实现 core.ProtocolListener 接口
// ========================================

// Listener HTTP协议监听器
type Listener struct {
	tunnelID  string
	port      string
	listener  net.Listener
	forwarder core.QUICForwarder
	ctx       context.Context
	cancel    context.CancelFunc
	stats     core.ProtocolStats
	isRunning atomic.Bool
}

// NewListener 创建HTTP协议监听器
func NewListener(tunnelID, port string, forwarder core.QUICForwarder) *Listener {
	ctx, cancel := context.WithCancel(context.Background())
	return &Listener{
		tunnelID:  tunnelID,
		port:      port,
		forwarder: forwarder,
		ctx:       ctx,
		cancel:    cancel,
	}
}

// Start 实现 ProtocolListener 接口
func (l *Listener) Start() error {
	if l.isRunning.Load() {
		return fmt.Errorf("监听器已在运行")
	}

	listener, err := net.Listen("tcp", fmt.Sprintf(":%s", l.port))
	if err != nil {
		return fmt.Errorf("HTTP监听失败: %w", err)
	}

	l.listener = listener
	l.isRunning.Store(true)

	log.Printf("🌐 HTTP公共端口监听启动成功: :%s -> 隧道 %s", l.port, l.tunnelID)

	// 启动监听循环
	go l.acceptLoop()

	return nil
}

// Stop 实现 ProtocolListener 接口
func (l *Listener) Stop() error {
	if !l.isRunning.Load() {
		return nil
	}

	l.cancel()
	if l.listener != nil {
		l.listener.Close()
	}
	l.isRunning.Store(false)

	log.Printf("🛑 HTTP监听器已停止: :%s", l.port)
	return nil
}

// GetProtocolType 实现 ProtocolListener 接口
func (l *Listener) GetProtocolType() core.ProtocolType {
	return core.ProtocolHTTP
}

// GetPort 实现 ProtocolListener 接口
func (l *Listener) GetPort() string {
	return l.port
}

// HandleConnection 实现 ProtocolListener 接口
func (l *Listener) HandleConnection(clientConn net.Conn) {
	defer clientConn.Close()

	clientAddr := clientConn.RemoteAddr().String()
	atomic.AddInt64(&l.stats.TotalRequests, 1)
	atomic.AddInt64(&l.stats.ActiveRequests, 1)
	defer atomic.AddInt64(&l.stats.ActiveRequests, -1)

	log.Printf("🌐 收到HTTP连接: 客户端=%s, 隧道ID=%s", clientAddr, l.tunnelID)

	// 🚀 取消读取超时，避免大文件传输超时
	// clientConn.SetReadDeadline(time.Now().Add(30 * time.Second))

	// 读取HTTP请求
	buf := &bytes.Buffer{}
	reader := bufio.NewReader(clientConn)

	// 读取请求行和头部
	for {
		line, err := reader.ReadBytes('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			log.Printf("❌ 读取HTTP请求失败: %v", err)
			atomic.AddInt64(&l.stats.ErrorCount, 1)
			return
		}

		buf.Write(line)

		// 检查是否到达头部结束（空行）
		if len(line) == 2 && line[0] == '\r' && line[1] == '\n' {
			break
		}
	}

	// 读取请求体（如果有）
	// 这里简化处理，实际应该根据Content-Length读取
	httpReq := buf.Bytes()
	atomic.AddInt64(&l.stats.TotalBytesRecv, int64(len(httpReq)))

	// 生成请求ID
	requestID := fmt.Sprintf("%s-%019d", l.tunnelID[:16], time.Now().UnixNano())

	// 🚀 重要修改：流式转发，直接传递clientConn给forwarder
	// forwarder会将响应流式写入clientConn，支持大文件传输
	err := l.forwarder.ForwardHTTPRequestStream(l.tunnelID, requestID, httpReq, clientConn)
	if err != nil {
		log.Printf("❌ [HTTP转发] 转发失败: %v", err)
		atomic.AddInt64(&l.stats.ErrorCount, 1)
		// 返回502错误
		errorResp := "HTTP/1.1 502 Bad Gateway\r\n\r\nTunnel forwarding failed"
		clientConn.Write([]byte(errorResp))
		return
	}

	atomic.AddInt64(&l.stats.SuccessCount, 1)
	log.Printf("✅ [HTTP转发] 请求完成: RequestID=%s", requestID[:8]+"...")
}

// acceptLoop 接受连接循环
func (l *Listener) acceptLoop() {
	for {
		select {
		case <-l.ctx.Done():
			return
		default:
		}

		clientConn, err := l.listener.Accept()
		if err != nil {
			select {
			case <-l.ctx.Done():
				return
			default:
				log.Printf("⚠️ 接受HTTP连接失败: %v", err)
				continue
			}
		}

		// 处理连接
		go l.HandleConnection(clientConn)
	}
}

// GetStats 获取统计信息
func (l *Listener) GetStats() core.ProtocolStats {
	return core.ProtocolStats{
		TotalRequests:  atomic.LoadInt64(&l.stats.TotalRequests),
		ActiveRequests: atomic.LoadInt64(&l.stats.ActiveRequests),
		TotalBytesSent: atomic.LoadInt64(&l.stats.TotalBytesSent),
		TotalBytesRecv: atomic.LoadInt64(&l.stats.TotalBytesRecv),
		SuccessCount:   atomic.LoadInt64(&l.stats.SuccessCount),
		ErrorCount:     atomic.LoadInt64(&l.stats.ErrorCount),
	}
}
